package com.example.demo.service;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 用户业务逻辑层（Service）
 * 负责处理业务逻辑，调用 Repository 进行数据访问
 *
 * @Service - 声明这是一个服务层组件，Spring 会自动扫描并注册为 Bean
 * @RequiredArgsConstructor - Lombok 注解，自动生成包含 final 字段的构造函数（用于依赖注入）
 * @Slf4j - Lombok 注解，自动生成日志对象 log
 * @Transactional - 声明事务管理，方法执行失败时自动回滚
 */
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional
public class UserService {

    // 依赖注入 UserRepository
    // final 修饰表示必须初始化，配合 @RequiredArgsConstructor 实现构造函数注入
    private final UserRepository userRepository;

    /**
     * 创建新用户
     * 业务逻辑：检查邮箱是否已存在，如果存在则抛出异常
     *
     * @param user 用户对象
     * @return 保存后的用户对象（包含生成的 ID）
     * @throws RuntimeException 如果邮箱已存在
     */
    public User createUser(User user) {
        log.info("开始创建用户: {}", user.getEmail());

        // 检查邮箱是否已存在
        if (userRepository.existsByEmail(user.getEmail())) {
            log.error("邮箱已存在: {}", user.getEmail());
            throw new RuntimeException("邮箱已存在: " + user.getEmail());
        }

        // 保存用户到数据库
        User savedUser = userRepository.save(user);
        log.info("用户创建成功，ID: {}", savedUser.getId());

        return savedUser;
    }

    /**
     * 根据 ID 获取用户
     *
     * @param id 用户ID
     * @return 用户对象
     * @throws RuntimeException 如果用户不存在
     */
    @Transactional(readOnly = true) // 只读事务，提高性能
    public User getUserById(Long id) {
        log.info("查询用户，ID: {}", id);

        return userRepository.findById(id)
                .orElseThrow(() -> {
                    log.error("用户不存在，ID: {}", id);
                    return new RuntimeException("用户不存在，ID: " + id);
                });
    }

    /**
     * 获取所有用户
     *
     * @return 用户列表
     */
    @Transactional(readOnly = true)
    public List<User> getAllUsers() {
        log.info("查询所有用户");
        return userRepository.findAll();
    }

    /**
     * 根据姓名模糊查询用户
     *
     * @param name 用户姓名（支持部分匹配）
     * @return 匹配的用户列表
     */
    @Transactional(readOnly = true)
    public List<User> searchUsersByName(String name) {
        log.info("模糊查询用户，姓名包含: {}", name);
        return userRepository.findByNameContaining(name);
    }

    /**
     * 更新用户信息
     * 业务逻辑：
     * 1. 检查用户是否存在
     * 2. 如果修改了邮箱，检查新邮箱是否已被其他用户使用
     * 3. 更新用户信息
     *
     * @param id 用户ID
     * @param user 新的用户信息
     * @return 更新后的用户对象
     * @throws RuntimeException 如果用户不存在或邮箱已被占用
     */
    public User updateUser(Long id, User user) {
        log.info("更新用户，ID: {}", id);

        // 1. 检查用户是否存在
        User existingUser = userRepository.findById(id)
                .orElseThrow(() -> {
                    log.error("用户不存在，ID: {}", id);
                    return new RuntimeException("用户不存在，ID: " + id);
                });

        // 2. 如果修改了邮箱，检查新邮箱是否已被其他用户使用
        if (!existingUser.getEmail().equals(user.getEmail())) {
            userRepository.findByEmail(user.getEmail()).ifPresent(u -> {
                if (!u.getId().equals(id)) {
                    log.error("邮箱已被其他用户使用: {}", user.getEmail());
                    throw new RuntimeException("邮箱已被其他用户使用: " + user.getEmail());
                }
            });
        }

        // 3. 更新用户信息
        existingUser.setName(user.getName());
        existingUser.setEmail(user.getEmail());

        User updatedUser = userRepository.save(existingUser);
        log.info("用户更新成功，ID: {}", updatedUser.getId());

        return updatedUser;
    }

    /**
     * 删除用户
     *
     * @param id 用户ID
     * @throws RuntimeException 如果用户不存在
     */
    public void deleteUser(Long id) {
        log.info("删除用户，ID: {}", id);

        // 检查用户是否存在
        if (!userRepository.existsById(id)) {
            log.error("用户不存在，ID: {}", id);
            throw new RuntimeException("用户不存在，ID: " + id);
        }

        // 删除用户
        userRepository.deleteById(id);
        log.info("用户删除成功，ID: {}", id);
    }
}
